#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include "student.hxx"
#include "student-odb.hxx"
#include <gflags/gflags.h>
#include <iostream>

DEFINE_string(host, "127.0.0.1", "Mysql数据库地址");
DEFINE_string(user, "root", "用户名");
DEFINE_string(pswd, "123456", "用户密码");
DEFINE_int32(port, 0, "数据库端口号");
DEFINE_string(db, "TestDB", "数据库名");
DEFINE_string(cset, "utf8", "字符集");
DEFINE_int32(max_pool, 3, "连接池最大连接数");

void insert_classes(odb::database& db) {
    try {
        // 从数据库连接获取事务，开启事务
        odb::transaction t(db.begin());
        Classes c1("一年级一班");
        Classes c2("一年级二班");
        //将对象持久化到数据库（插入操作）
        db.persist(c1);
        db.persist(c2);
        // 提交事务
        t.commit();
    } catch (std::exception& e) {
        std::cout << "更新学生数据出错：" << e.what() << std::endl;
    }
}

void insert_student(odb::mysql::database &db) {
    try {
        //获取事务对象
        odb::transaction trans(db.begin());
        Student s1(1, "张三", 18, 1);
        Student s2(2, "张四", 19, 1);
        Student s3(3, "张五", 15, 1);
        Student s4(4, "张六", 17, 2);
        Student s5(5, "张七", 16, 2);
        Student s6(6, "张八", 14, 2);
        db.persist(s1);
        db.persist(s2);
        db.persist(s3);
        db.persist(s4);
        db.persist(s5);
        db.persist(s6);

        //提交事务
        trans.commit();
    } catch (std::exception &e) {
        std::cout << "插入学生数据错误" << e.what() << std::endl;
    }
}

Student select_student(odb::mysql::database &db) {
    Student res;
    try {
        //获取事务对象开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<Student> result;
        result r(db.query<Student>(query::name == "张三"));
        if (r.size() != 1) {
            std::cout << "数据量错误！\n";
            return Student();
        }
        res = *r.begin();

        trans.commit();
    } catch (std::exception &e) {
        std::cout << "查询学生数据错误" << e.what() << std::endl;
    }
    return res;
}

void update_student(odb::mysql::database &db, Student &stu) {
    try {
        //获取事务对象开启事务
        odb::transaction trans(db.begin());
        db.update(stu);

        trans.commit();
    } catch (std::exception &e) {
        std::cout << "移除学生数据出错：" << e.what() << std::endl;
    }
}

void remove_student(odb::mysql::database &db) {
    try {
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        db.erase_query<Student>(query::classes_id == 2);

        trans.commit();
    } catch (std::exception &e) {
        std::cout << "更新学生数据出错：" << e.what() << std::endl;
    }
}

void classes_student(odb::mysql::database &db) {
    try {
        odb::transaction trans(db.begin());
        typedef odb::query<struct classes_student> query;
        typedef odb::result<struct classes_student> result;
        result r(db.query<struct classes_student>(query::classes::id == 1));
        // result r(db.query<struct classes_student>(query::Student::age == 20));
        for (auto it = r.begin(); it != r.end(); it++) {
            std::cout << it->id << " " 
                      << it->sn << " " 
                      << it->name << " "
                      << *it->age << " "
                      << it->classes_name << std::endl;
        }
    } catch (std::exception &e) {
        std::cout << "查询学生数据出错：" << e.what() << std::endl;
    }
}

void all_student(odb::mysql::database &db) {
    try {
        //获取事务对象开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<struct all_name> result;
        result r(db.query<struct all_name>(query::id == 1));
        for (auto it = r.begin(); it != r.end(); ++it) {
            std::cout << it->name << std::endl;
        }
        //5. 提交事务
        trans.commit();
    }catch (std::exception &e) {
        std::cout << "查询所有学生姓名数据出错：" << e.what() << std::endl;
    }
}

int main(int argc, char* argv[]) {
    google::ParseCommandLineFlags(&argc, &argv, true);
    //1. 构造连接池工厂配置对象
    std::unique_ptr<odb::mysql::connection_pool_factory> cpf(
        new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));
    
    //2. 构造数据库对操作象
    odb::mysql::database db(
        FLAGS_user, FLAGS_pswd, FLAGS_db,
        FLAGS_host, FLAGS_port, "", FLAGS_cset,
        0, std::move(cpf));
    
    //数据库操作
    //insert_classes(db);

    //insert_student(db);

    // auto stu = select_student(db);
    // std::cout << stu.sn() << std::endl;
    // std::cout << stu.name() << std::endl;
    // if (stu.age()) std::cout << *stu.age() << std::endl;
    // std::cout << stu.classes_id() << std::endl;
    
    // stu.age(20);
    // update_student(db, stu);

    //remove_student(db);

    //根据班级 ID（此处为 1）查询该班级下的学生信息
    //classes_student(db);

    all_student(db);
    return 0;
}